/**
  ******************************************************************************
  * @文件名称 : task_communication.c
  * @摘要 : 
  * @创建日期 : Jul 23, 2024
  * @创建者：citunhk
  ******************************************************************************
  * @使用说明
  *
  *  
  ******************************************************************************
  */

/* 声明包含头文件 -----------------------------------------------------------*/
#include "main.h"
#include "../Inc/task_communication.h"
#include "../../03_FML/MODBUS/Inc/agile_modbus_rtu.h"
#include "../../03_FML/RINGBUF/ringbuffer.h"
#include "../../02_BLL/Res/Inc/data_public.h"
/* 声明私有宏定义 -----------------------------------------------------------*/
#define UART_RX_RB_BUFSZ 1024
//#define BigtoLittle16(A)   (( ((uint16_t)(A) & 0xff00) >> 8)    | \
//							   (( (uint16_t)(A) & 0x00ff) << 8))
//#define BigtoLittle32(A)   ((( (uint32_t)(A) & 0xff000000) >> 24) | \
//							   (( (uint32_t)(A) & 0x00ff0000) >> 8)   | \
//							   (( (uint32_t)(A) & 0x0000ff00) << 8)   | \
//							   (( (uint32_t)(A) & 0x000000ff) << 24))
//#define HighttoLowFloat(A)   ((( (uint32_t)(A) & 0xffff0000) >> 16) | \
//							   (( (uint32_t)(A) & 0x0000ffff) << 16)   | \
/* 声明私有类型定义---------------------------------------------------------*/
struct usart_t{
	UART_HandleTypeDef* huart;//串口句柄
	DMA_HandleTypeDef* hdma_rx;
	DMA_HandleTypeDef* hdma_tx;
	uint32_t rx_tick_timeout;//接收超时
	struct rt_ringbuffer rx_rb;//接收环形缓冲区结构体
	uint8_t rx_rb_buf[UART_RX_RB_BUFSZ];//接收环形缓存区数据
	uint32_t rx_index;//接收索引
	int rx_rb_used_len;
	int rx_rb_unused_len;
	uint32_t byte_timeout;//字节间隔超时
	uint32_t tx_tick_timeout;//发送超时
	uint32_t tx_complete;//发送完成标志
//	void (*tx_en)(void);//发送管脚使能
//	void (*rx_en)(void);//接收管脚使能
	struct global_attr gbl_attr;
};
/* 声明私有变量 -------------------------------------------------------------*/
extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart3;

volatile static struct usart_t modbus = {  //RS232or485 Master
#ifndef MODBUS_MASTER_RS485  //RS232使用的串口1
		.huart = &huart1,
		.hdma_rx = &hdma_usart1_rx,
		.hdma_tx = &hdma_usart1_tx,
#else
		.huart = &huart3,  //RS485使用的串口5
		.hdma_rx = &hdma_usart3_rx,
		.hdma_tx = &hdma_usart3_tx,
#endif
		.rx_tick_timeout = 0,
		.rx_rb = {0},
		.rx_rb_buf = {0},
		.rx_index = 0,
		.byte_timeout = 0,
		.tx_tick_timeout = 0,
		.tx_complete = 0,
#ifdef MODBUS_MASTER_RS485
		.tx_en = USART3_TX_EN,
		.rx_en = USART3_RX_EN,
#endif
		.gbl_attr =  {0},
};

uint16_t _tab_registers[120] = {0};
int set_index = 0;
int set_len = 0;
/* 声明私有常量 -------------------------------------------------------------*/

/* 声明私有函数 -------------------------------------------------------------*/
/**
  * @brief  主机接收
  * @param  无
  * @retval 无
  */
static int _master_receive(struct usart_t* modbus, uint8_t *buf, int bufsz, int timeout, int bytes_timeout, int *state)
{
    switch (*state) {
    case RS485_RECV_STATE_START: {
    	modbus->rx_rb_used_len = 0;
    	modbus->rx_rb_unused_len = bufsz;
        __disable_irq();
        modbus->rx_tick_timeout = HAL_GetTick() + timeout;
        modbus->byte_timeout = bytes_timeout;
        __enable_irq();
        *state = RS485_RECV_STATE_WAIT_FIRST;
    } break;

    case RS485_RECV_STATE_WAIT_FIRST: {
        if (rt_ringbuffer_data_len(&modbus->rx_rb) > 0) {
            *state = RS485_RECV_STATE_WAIT_BYTE;

            __disable_irq();
            modbus->rx_tick_timeout = HAL_GetTick() + modbus->byte_timeout;
            __enable_irq();
        } else {
            if ((HAL_GetTick() - modbus->rx_tick_timeout) < (HAL_TICK_MAX / 2))
                *state = RS485_RECV_STATE_FINISH;
        }
    } break;

    case RS485_RECV_STATE_WAIT_BYTE: {
        if (rt_ringbuffer_data_len(&modbus->rx_rb) > 0) {
            __disable_irq();
            int rc = rt_ringbuffer_get(&modbus->rx_rb, buf + modbus->rx_rb_used_len, modbus->rx_rb_unused_len);
            __enable_irq();

            modbus->rx_rb_used_len += rc;
            modbus->rx_rb_unused_len -= rc;

            if (modbus->rx_rb_unused_len == 0) {
                *state = RS485_RECV_STATE_FINISH;
                break;
            }
        } else {
            if ((HAL_GetTick() - modbus->rx_tick_timeout) < (HAL_TICK_MAX / 2))
                *state = RS485_RECV_STATE_FINISH;
        }
    } break;

    default:
        break;
    }

    return modbus->rx_rb_used_len;
}

/**
  * @brief  主机发送
  * @param  无
  * @retval 无
  */
static int _master_send(struct usart_t* modbus, uint8_t *buf, int len, int timeout, int *state)
{
    int send_len = 0;

    switch (*state) {
    case RS485_SEND_STATE_START: {
        *state = RS485_SEND_STATE_WAIT;
//        if(modbus->tx_en != NULL)
//        	modbus->tx_en();
        HAL_UART_AbortTransmit(modbus->huart);  //重置串口通讯状态
        modbus->tx_complete = 0;
        HAL_UART_Transmit_DMA(modbus->huart, buf, len);  //启动DMA传输
        modbus->tx_tick_timeout = HAL_GetTick() + timeout;
    } break;

    case RS485_SEND_STATE_WAIT: {
        if (modbus->tx_complete) {
            send_len = len;
            *state = RS485_SEND_STATE_FINISH;
        } else {
            if ((HAL_GetTick() - modbus->tx_tick_timeout) < (HAL_TICK_MAX / 2))
                *state = RS485_SEND_STATE_FINISH;
        }
    } break;

    default: {
        HAL_UART_AbortTransmit(modbus->huart);  //停止数据发送
//        if(modbus->rx_en != NULL)
//        	modbus->rx_en();
    } break;
    }

    return send_len;
}
static int _rx_rb_update(struct usart_t* modbus, uint32_t size)
{
    if (rt_ringbuffer_put_update(&modbus->rx_rb, size) != size)
        return -1;

    return 0;
}
static void rs485_flush(struct usart_t* modbus)
{
    rt_ringbuffer_init(&modbus->rx_rb, modbus->rx_rb_buf, sizeof(modbus->rx_rb_buf));
    HAL_UART_AbortReceive(modbus->huart);
    HAL_UART_Receive_DMA(modbus->huart, modbus->rx_rb.buffer_ptr, modbus->rx_rb.buffer_size);
    modbus->rx_index = modbus->rx_rb.buffer_size;
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart == modbus.huart)
	{
		HAL_UART_AbortTransmit(modbus.huart);
//			if(modbus.rx_en != NULL)
//				modbus.rx_en();
		modbus.tx_complete = 1;
	}
}
static void UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	uint32_t recv_len = 0;

	uint32_t index;
	if(huart == modbus.huart)
	{
		index = __HAL_DMA_GET_COUNTER(modbus.hdma_rx);
		if (index >= modbus.rx_index) {
			recv_len = modbus.rx_index + modbus.rx_rb.buffer_size - index;
			modbus.rx_index = index;
		}

		if (recv_len > 0) {
			if (_rx_rb_update(&modbus, recv_len) < 0)
				rs485_flush(&modbus);
			else
				modbus.rx_tick_timeout = HAL_GetTick() + modbus.byte_timeout;
		}
	}

}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	UART_RxCpltCallback(huart);
}

void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)
{
	UART_RxCpltCallback(huart);
}

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
	if(huart == modbus .huart)
	{
		if(__HAL_UART_GET_FLAG(modbus.huart, UART_FLAG_FE) ||
		   __HAL_UART_GET_FLAG(modbus.huart, UART_FLAG_NE) ||
		   __HAL_UART_GET_FLAG(modbus.huart, UART_FLAG_ORE))
		{
			if (__HAL_UART_GET_FLAG(modbus.huart, UART_FLAG_LBD))
			{
				// 清除LBD标志位
				__HAL_UART_CLEAR_FLAG(modbus.huart, UART_FLAG_LBD);
			}
			HAL_UART_AbortReceive(modbus.huart);  //中止接收
			HAL_UART_Receive_DMA(modbus.huart, modbus.rx_rb.buffer_ptr, modbus.rx_rb.buffer_size);  //DMA接收
		}
	}
}
//void HAL_UART_IdleCpltCallback(UART_HandleTypeDef *huart)
//{
//	uint32_t index = 0;
//	uint32_t recv_len = 0;
//
//	if(huart == modbus.huart)
//	{
//		__disable_irq();
//		do {
//			index = __HAL_DMA_GET_COUNTER(modbus.hdma_rx);
//			if (index >= modbus.rx_index)
//				break;
//			if (__HAL_DMA_GET_FLAG(modbus.hdma_rx, __HAL_DMA_GET_HT_FLAG_INDEX(modbus.hdma_rx)) != RESET)
//				break;
//			if (__HAL_DMA_GET_FLAG(modbus.hdma_rx, __HAL_DMA_GET_TC_FLAG_INDEX(modbus.hdma_rx)) != RESET)
//				break;
//
//			recv_len = modbus.rx_index - index;
//			modbus.rx_index = index;
//
//			if (recv_len > 0) {
//				if (_rx_rb_update(&modbus, recv_len) < 0)
//					rs485_flush(&modbus);
//				else
//					modbus.rx_tick_timeout = HAL_GetTick() + modbus.byte_timeout;
//			}
//		} while (0);
//		__enable_irq();
//
//		int rc = rt_ringbuffer_data_len(&modbus.rx_rb);
//		if (rc > 0)
//		{
//			modbus.rx_rb_used_len = 0;
//			modbus.rx_rb_unused_len = 120;
//
//			set_index = 0;
//			set_len = rc/2;
////			task_event_send(TASK_INDEX_COMM_MB_RTU_M, 0x01);
////			task_event_send(TASK_INDEX_LED_DT2, 1);
//
//			__disable_irq();
//	#if BigLittleSwapEnable
//			rc = rt_ringbuffer_get(&modbus.rx_rb, (uint8_t *)&tempRegisters[0], modbus.rx_rb_unused_len);
//	#else
//			rc = rt_ringbuffer_get(&modbus.rx_rb, (uint8_t *)&_tab_registers[0], modbus.rx_rb_unused_len);
//	#endif
//			__enable_irq();
//
//	#if BigLittleSwapEnable
//			for(uint8_t i = 0; i < rc / 2; i++)
//			{
//				_tab_registers[i] = (((tempRegisters[i]) & 0xff00) >> 8) | (((tempRegisters[i]) & 0x00ff) << 8);
//			}
//	#endif
//
//			modbus.rx_rb_used_len += rc;
//			modbus.rx_rb_unused_len -= rc;
//
//			if (modbus.rx_rb_unused_len == 0) {
//			}
//		} else {
//		}
//	}
//}
static int task_entry_monitor(void)
{
    uint32_t index = 0;

	index = __HAL_DMA_GET_COUNTER(modbus.hdma_rx);
	if (index >= modbus.rx_index)
		return 0;

	uint32_t recv_len = 0;

	__disable_irq();
	do {
		index = __HAL_DMA_GET_COUNTER(modbus.hdma_rx);
		if (index >= modbus.rx_index)
			break;
		if (__HAL_DMA_GET_FLAG(modbus.hdma_rx, __HAL_DMA_GET_HT_FLAG_INDEX(modbus.hdma_rx)) != RESET)
			break;
		if (__HAL_DMA_GET_FLAG(modbus.hdma_rx, __HAL_DMA_GET_TC_FLAG_INDEX(modbus.hdma_rx)) != RESET)
			break;

		recv_len = modbus.rx_index - index;
		modbus.rx_index = index;

		if (recv_len > 0) {
			if (_rx_rb_update(&modbus, recv_len) < 0)
				rs485_flush(&modbus);
			else
				modbus.rx_tick_timeout = HAL_GetTick() + modbus.byte_timeout;
		}
	} while (0);
	__enable_irq();

    return 0;
}

/**
  * @brief  主机通讯
  * @param  无
  * @retval 无
  */
int bll_communication(struct task_pcb *task)
{
#define PROCESS_INTERVAL 300

    static int __tx_state = RS485_SEND_STATE_START;  //发送状态
    static int __rx_state = RS485_RECV_STATE_START;  //读取状态
    static int __send_len = 0;  //发送长度
    static int __read_len = 0;  //读取长度

    static uint32_t __tick_timeout = 0;  //超时
    static uint8_t __read_step = 0;	 //读取步骤
    static uint8_t timeout_cnt = 0;  //超时计数
    static uint8_t flag_WR = 0;  //读写标志
    static uint8_t time = 0;

    int *run_step = &modbus.gbl_attr.modbus_step[modbus.gbl_attr.modbus_mode];  //状态机状态指针
    agile_modbus_t *ctx = &modbus.gbl_attr.ctx_rtu._ctx;
    /* 判断是否有更新全部参数的指令 */
    if (g_updateScreenFlag == 1 && CA.flagWrite == 0)  // 判断是否更新且写空闲
    {
    	g_updateScreenFlag = 0;
    	__read_step = 0;  //重新读取全部数据
    	*run_step = 1;
    }
    if(++time == 10)
    {
    	time = 0;
    	task_entry_monitor();
    }
	switch(*run_step){
	case 0:{  //初始化状态
		rt_ringbuffer_init(&modbus.rx_rb, modbus.rx_rb_buf, sizeof(modbus.rx_rb_buf));  //初始化环形缓冲区
		HAL_UART_AbortReceive(modbus.huart);  //中止接收
		HAL_UART_Receive_DMA(modbus.huart, modbus.rx_rb.buffer_ptr, modbus.rx_rb.buffer_size);  //DMA接收
		modbus.rx_index = modbus.rx_rb.buffer_size;

		//初始化
        agile_modbus_rtu_init(&modbus.gbl_attr.ctx_rtu,   //指向 Modbus RTU 上下文结构的指针
        		modbus.gbl_attr.ctx_send_buf, sizeof(modbus.gbl_attr.ctx_send_buf),  //发送缓冲区的指针  发送缓冲区的大小
        		modbus.gbl_attr.ctx_read_buf1, sizeof(modbus.gbl_attr.ctx_read_buf1));  //接收缓冲区指针
        agile_modbus_set_slave(ctx, 1);  //设置从机地址为1
        *run_step = 1;
	}break;
	case 1:{  //装载指令状态
    	modbus.gbl_attr.modbus_total_cnt[modbus.gbl_attr.modbus_mode]++;  //装载计数
        __tx_state = RS485_SEND_STATE_START;  //恢复发送状态为开始
        __rx_state = RS485_RECV_STATE_START;  //恢复接收状态为开始
        if((CA.flagWrite) && (timeout_cnt++ < 3))  //上位机发送写寄存器指令且写入失败没有到达3次
		{
			if(CA.sumReg == 1)
				__send_len = agile_modbus_serialize_write_register(ctx, CA.commAddr, *CA.ramAddr);/* 写单个寄存器 */
			else if(CA.sumReg > 1)
				__send_len = agile_modbus_serialize_write_registers(ctx, CA.commAddr, CA.sumReg, CA.ramAddr);  /* 写多个寄存器 */

			flag_WR = 1;
		}
        else  //上位机发送读寄存器指令或写入失败到达3次
        {
        	if(loadingValue < 99)
        	{
        		break;
        	}
        	task->event &= (~0x01);  //清除写指令标志位
        	CA.flagWrite = 0;  //清除写入指令
        	timeout_cnt = 0;  //等待时间清零
        	switch(__read_step)
        	{
        	case 0:
				__send_len = agile_modbus_serialize_read_registers(ctx, 100-1, 100);/* 40100-40199 */
				break;
        	case 1:
				__send_len = agile_modbus_serialize_read_registers(ctx, 200-1, 100);/* 40200-40299 */
				break;
        	case 2:
				__send_len = agile_modbus_serialize_read_registers(ctx, 300-1, 60);/* 40300-40359 */
				break;
        	case 3:
				__send_len = agile_modbus_serialize_read_registers(ctx, 1000-1, 100);/* 41000-41099 */
				break;
        	case 4:
				__send_len = agile_modbus_serialize_read_registers(ctx, 1100-1, 100);/* 41100-41199 */
				break;
				/* 以上内容为开机时读取一次 */
        	case 5:
        		__send_len = agile_modbus_serialize_read_registers(ctx, 100-1, 60);/* 40100-40159 */
        		break;
        	case 6:
        		__send_len = agile_modbus_serialize_read_registers(ctx, 210-1, 20);/* 40210-40229 */
        		break;
        	case 7:
        		__send_len = agile_modbus_serialize_read_registers(ctx, 286-1, 5);/* 40286-40290 */
        		break;
        	case 8:
				__send_len = agile_modbus_serialize_read_registers(ctx, 500-1, 50);/* 40500-40549 */
				break;
        	default:
        		__read_step = 5;
        		break;
        	}
        }
        *run_step = 2;
	}break;
	case 2:{  //发送指令状态
        int rc = _master_send(&modbus, ctx->send_buf, __send_len, 1000, &__tx_state);  //判断发送状态并执行相应动作
        if (__tx_state == RS485_SEND_STATE_FINISH) {  //发送完成
            if (rc != __send_len) {  //硬件发送失败
                *run_step = 5;
//                LOG_I("send timeout.");
//                task_event_send(TASK_INDEX_LED_ERR, 1);
                __tick_timeout = HAL_GetTick() + PROCESS_INTERVAL;
            } else{  //硬件发送成功
                *run_step = 3;
//            	task_event_send(TASK_INDEX_LED_DT1, 1);
            }
        }
	}break;
	case 3:{  //接收指令状态
	      __read_len = _master_receive(&modbus, ctx->read_buf, ctx->read_bufsz, 1000, 50, &__rx_state);  //判断接收状态并执行相应动作
	        if (__rx_state == RS485_RECV_STATE_FINISH) {  //接收完成
	            if (__read_len == 0) {  //未接收到数据
	                *run_step = 5;
//	                LOG_I("recv timeout.");
//	                task_event_send(TASK_INDEX_LED_ERR, 1);
	                _tab_registers[80] = 0;
//	                task_event_send(TASK_INDEX_COMM_CHOOSE, 2);
	                __tick_timeout = HAL_GetTick() + PROCESS_INTERVAL;
	            } else  //接受到数据
	                *run_step = 4;
	        }
	}break;
	case 4:{  //解析指令状态
   	 int rc;
   	 if(CA.flagWrite)  //写入指令
   	 {
   		 if(flag_WR)
   		 {
   			 CA.flagWrite = 0;  //清除写入指令
			 timeout_cnt = 0;
			 flag_WR = 0;
			if(CA.sumReg == 1)
				rc = agile_modbus_deserialize_write_register(ctx, __read_len);
			else if(CA.sumReg > 1)
				rc = agile_modbus_deserialize_write_registers(ctx, __read_len);  //接收到的消息长度
   		 }
   	 }
   	 else  //读取指令
   	 {
   		switch(__read_step)
		{
   		case 0:/* 40100-40199 */
			rc = agile_modbus_deserialize_read_registers(ctx, __read_len, (uint16_t *)&UP);  //读取到的长度和存储数据的指针  返回读取的寄存器数量  -1是异常
//			__read_step++;
			break;
		case 1:/* 40200-40299 */
			rc = agile_modbus_deserialize_read_registers(ctx, __read_len, (uint16_t *)&UP+100);  //读取到的长度和存储数据的指针  返回读取的寄存器数量  -1是异常
//			__read_step++;
			break;
		case 2:/* 40300-40359 */
			rc = agile_modbus_deserialize_read_registers(ctx, __read_len, (uint16_t *)&UP+200);  //读取到的长度和存储数据的指针  返回读取的寄存器数量  -1是异常
//			__read_step++;
			break;
		case 3:/* 41000-41099 */
			rc = agile_modbus_deserialize_read_registers(ctx, __read_len, (uint16_t *)&FP);  //读取到的长度和存储数据的指针  返回读取的寄存器数量  -1是异常
//			__read_step++;
			break;
		case 4:/* 41100-41199 */
			rc = agile_modbus_deserialize_read_registers(ctx, __read_len, (uint16_t *)&FP+100);  //读取到的长度和存储数据的指针  返回读取的寄存器数量  -1是异常
//			__read_step++;
			break;

		case 5:/* 40100-40159 */
			rc = agile_modbus_deserialize_read_registers(ctx, __read_len, (uint16_t *)&UP);  //读取到的长度和存储数据的指针  返回读取的寄存器数量  -1是异常
//			__read_step++;
			break;
		case 6:/* 40210-40229 */
			rc = agile_modbus_deserialize_read_registers(ctx, __read_len, (uint16_t *)&UP+110);  //读取到的长度和存储数据的指针  返回读取的寄存器数量  -1是异常
//			__read_step++;
			break;
		case 7:/* 40286-40290 */
			rc = agile_modbus_deserialize_read_registers(ctx, __read_len, (uint16_t *)&UP+186);  //读取到的长度和存储数据的指针  返回读取的寄存器数量  -1是异常
//			__read_step++;
			break;
		case 8:/* 40500-40549 */
			rc = agile_modbus_deserialize_read_registers(ctx, __read_len, (uint16_t *)&UP+400);  //读取到的长度和存储数据的指针  返回读取的寄存器数量  -1是异常
//			__read_step = 5;
			break;
		default:
//			__read_step = 5;
			break;
		}

   	 }
       if (rc < 0) {  //通讯异常
//           LOG_W("Receive failed.");
//           task_event_send(TASK_INDEX_LED_ERR, 1);
       } else {  //通讯正常
       	modbus.gbl_attr.modbus_success_cnt[modbus.gbl_attr.modbus_mode]++;  //通讯成功计数
//           LOG_I("Hold Registers:");
//           for (int i = 0; i < 10; i++)
//               LOG_I("Register [%d]: 0x%04X", i, _tab_registers[i]);
//           task_event_send(TASK_INDEX_LED_DT1, 2);
//           printf("\r\n\r\n\r\n");
       }

       __tick_timeout = HAL_GetTick() + PROCESS_INTERVAL;
       *run_step = 5;
	}break;
	case 5:{  //间隔延时
        if ((HAL_GetTick() - __tick_timeout) >= (HAL_TICK_MAX / 2))  //获取启动时间
            break;
        if(++__read_step > 8)
        	__read_step = 5;
        *run_step = 1;
	}break;
	default:
		break;
	}

	return 1;

}






